package com.zhiche.wms.service.sys.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.zhiche.wms.core.supports.BaseException;
import com.zhiche.wms.domain.mapper.sys.RoleMapper;
import com.zhiche.wms.domain.model.sys.Permission;
import com.zhiche.wms.domain.model.sys.Role;
import com.zhiche.wms.domain.model.sys.RolePermission;
import com.zhiche.wms.domain.model.sys.UserRole;
import com.zhiche.wms.service.sys.IPermissionService;
import com.zhiche.wms.service.sys.IRolePermissionService;
import com.zhiche.wms.service.sys.IRoleService;
import com.zhiche.wms.service.sys.IUserRoleService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 角色 服务实现类
 * </p>
 *
 * @author zhaoguixin
 * @since 2018-06-19
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private IPermissionService permissionService;

    @Autowired
    private IRolePermissionService rolePermissionService;

    @Autowired
    private IUserRoleService userRoleService;

    @Override
    public boolean deleteRole(List<Integer> roleIds) throws Exception {
        if (Objects.equals(roleIds, null)) {
            logger.error("RoleServiceImpl.delRole param rids must not be null ");
            throw new IllegalArgumentException("角色id不能为空");
        }

        for (Integer id : roleIds) {
            Wrapper<UserRole> ew = new EntityWrapper<>();
            ew.eq("role_id", id);
            int count = userRoleService.selectCount(ew);
            if (count > 0) {
                throw new BaseException("id为" + id + "的角色存在相关用户，无法删除");
            }
        }

        if (deleteBatchIds(roleIds)) {
            Wrapper<RolePermission> rolePermissionEw = new EntityWrapper<>();
            rolePermissionEw.in("role_id", roleIds);
            return rolePermissionService.delete(rolePermissionEw);
        }
        return deleteBatchIds(roleIds);
    }

    @Override
    @Transactional
    public Integer assignPermission(Integer roleId, List<Integer> permissionIds) throws Exception {
        if (Objects.equals(roleId, null)) {
            logger.error("RoleServiceImpl.assignPermission param rid must not be null ");
            throw new IllegalArgumentException("角色id不能为空");
        }

        //得到所指派的权限
        List<Permission> assignPermissions = permissionService.selectBatchIds(permissionIds);
        List<Permission> allPermissions = permissionService.selectList(null);

        //迭代得到指派权限的上级权限(目录)，前端只传递叶子节点权限
        List<Permission> parentPerm = new ArrayList<>();
        for (Permission assign : assignPermissions) {
            setParentPermission(assign, parentPerm, allPermissions);
        }

        //得到不重复的权限
        List<Integer> assignPermissIds = getNoRepeatPermIds(assignPermissions, parentPerm);

        //获取数据库中的角色对应的权限
        EntityWrapper<RolePermission> ew = new EntityWrapper<>();
        ew.eq("role_id", roleId);
        List<RolePermission> dbRolePermissions = rolePermissionService.selectList(ew);

        List<Integer> dbRolePermissionIds = new ArrayList<>();
        dbRolePermissions.forEach(
                dbRolePermission -> dbRolePermissionIds.add(dbRolePermission.getPermissionId()));

        try {
            authorize(roleId, assignPermissIds, dbRolePermissionIds);
            return 1;
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 循环授权
     *
     * @param roleId              角色ID
     * @param assignPermissIds    新指派权限ID
     * @param dbRolePermissionIds 数据库已存权限ID
     */
    private void authorize(Integer roleId, List<Integer> assignPermissIds, List<Integer> dbRolePermissionIds)
            throws Exception {

        //循环删除数据库有，但指派权限中不包含的权限
        for (Integer permId : dbRolePermissionIds) {
            if (!assignPermissIds.contains(permId)) {
                EntityWrapper<RolePermission> ew = new EntityWrapper<>();
                ew.eq("role_id", roleId).eq("permission_id", permId);
                rolePermissionService.delete(ew);
            }
        }

        //循环增加指派权限中有，但数据库中不包含的权限
        for (Integer permissionId : assignPermissIds) {
            if (!dbRolePermissionIds.contains(permissionId)) {
                RolePermission rolePermission = new RolePermission();
                rolePermission.setRoleId(roleId);
                rolePermission.setPermissionId(permissionId);
                rolePermissionService.insert(rolePermission);
            }
        }
    }

    @Override
    public List<Permission> listOwnPermission(Integer roleId) {
        List<Permission> ownPermissions = baseMapper.selectRolePermission(roleId);
        if (Objects.equals(ownPermissions, null)) return null;
        List<Permission> menuPermissions = new LinkedList<>();
        for (Permission permission : ownPermissions) {
            if (permission.getType().equals(2)) {
                menuPermissions.add(permission);
            }
        }
        return menuPermissions;
    }

    @Override
    public List<Permission> listOwnAllPermission(Integer roleId) {
        List<Permission> ownPermissions = baseMapper.selectRolePermission(roleId);
        if (Objects.equals(ownPermissions, null)) return null;
        return ownPermissions;
    }

    /**
     * 分页查询角色
     */
    @Override
    public Page<Role> queryRolePage(Page<Role> page) {
        if (page == null) {
            throw new BaseException("page信息不能为空");
        }
        Map<String, Object> condition = page.getCondition();
        EntityWrapper<Role> ew = new EntityWrapper<>();
        if (condition != null && !condition.isEmpty()) {
            Object name = condition.get("name");
            Object status = condition.get("status");
            Object title = condition.get("title");
            if (name != null && StringUtils.isNotBlank(name.toString())) {
                ew.eq("name", name);
            }
            if (status != null && StringUtils.isNotBlank(status.toString())) {
                ew.eq("status", status);
            }
            if (title != null && StringUtils.isNotBlank(title.toString())) {
                ew.eq("title", title);
            }
        }
        ew.orderBy("id", false);
        return selectPage(page, ew);
    }

    @Override
    public List<Permission> getOwnBottomPermission(Integer roleId) {
        if (roleId == null) {
            throw new BaseException("角色id不能为空");
        }
        List<Permission> ownBottomPermissions = baseMapper.selectOwnBottomPermission(roleId);
        if (Objects.equals(ownBottomPermissions, null)) return null;
        return ownBottomPermissions;
    }

    /**
     * 设置父级目录
     */
    private void setParentPermission(Permission childPerm, List<Permission> result, List<Permission> source) {
        for (Permission perm : source) {
            if (perm.getId().equals(childPerm.getPid())) {
                result.add(perm);
                setParentPermission(perm, result, source);
            }
        }
    }

    /**
     * 得到不重复的权限ID
     */
    private List<Integer> getNoRepeatPermIds(List<Permission> parentMenu, List<Permission> parentDir) {
        List<Integer> permIds = new ArrayList<>();

        for (Permission permission : parentMenu) {
            if (!permIds.contains(permission.getId())) {
                permIds.add(permission.getId());
            }
        }

        for (Permission permission : parentDir) {
            if (!permIds.contains(permission.getId())) {
                permIds.add(permission.getId());
            }
        }
        return permIds;
    }

}
